package com.bonc.ioc.demo.aop;


import com.bonc.ioc.common.util.AppReply;
import com.bonc.ioc.demo.exception.McpException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.net.SocketTimeoutException;
import javax.validation.ConstraintViolationException;

/**
 * 全局的的异常拦截器（拦截所有的控制器）
 *
 * @author fengshuonan
 * @date 2016年11月12日 下午3:19:56
 */
@RestControllerAdvice
@Order(-1)
public class GlobalExceptionHandler {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Value("${spring.application.name:null}")
    private String applicationName;

    private static final String ERROR_MESSAGE_PREFIX = "Error:";

    @ExceptionHandler({DataIntegrityViolationException.class})
    @ResponseBody
    public AppReply requestMissingServletRequest(DataIntegrityViolationException ex) {
        String str = ex.getMessage();
        String param = str.substring(str.lastIndexOf("column '") + 8, str.lastIndexOf("'"));
        log.error("参数" + param + "超出长度限制");
        return AppReply.error("参数" + param + "超出长度限制");
    }

    /**
     * 捕捉实体类参数校验异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({BindException.class})
    @ResponseBody
    public AppReply bindException(BindException ex) {
        return AppReply.error(ex.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * 用来处理bean validation异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public AppReply resolveConstraintViolationException(ConstraintViolationException ex) {
        String str = ex.getMessage();
        String msg = str.substring(str.indexOf(":") + 1);
        return AppReply.error(msg.trim());
    }

    @ExceptionHandler(TransactionSystemException.class)
    @ResponseBody
    public AppReply resolveTransactionSystemException(TransactionSystemException e) {
        log.error("运行时异常: " + e.getMessage(), e);

        if (StringUtils.isNotEmpty(e.getMessage()) && e.getMessage().startsWith(ERROR_MESSAGE_PREFIX)) {
            // 如果有前置报错，说明该类型的错误已经报了，所以保持原有错误 为了保持原始的报错点信息
            return AppReply.error(e.getMessage());
        } else {
            StringBuffer stringBuffer = new StringBuffer(ERROR_MESSAGE_PREFIX);
            stringBuffer.append("数据库连接断开");
            return AppReply.error(stringBuffer.toString());
        }
    }

    @ExceptionHandler(ArrayIndexOutOfBoundsException.class)
    @ResponseBody
    public AppReply arrayIndexOutOfBoundsExceptionException(ArrayIndexOutOfBoundsException e) {
        log.error("运行时异常: " + e.getMessage(), e);

        if (StringUtils.isNotEmpty(e.getMessage()) && e.getMessage().startsWith(ERROR_MESSAGE_PREFIX)) {
            // 如果有前置报错，说明该类型的错误已经报了，所以保持原有错误 为了保持原始的报错点信息
            return AppReply.error(e.getMessage());
        } else {
            StringBuffer stringBuffer = new StringBuffer(ERROR_MESSAGE_PREFIX);
            stringBuffer.append("数组越界，请与管理员联系");
            return AppReply.error(stringBuffer.toString());
        }
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public AppReply notFount(RuntimeException e) {
        log.error("运行时异常: " + e.getMessage(), e);

        // 确定提示信息
        String message = e.getMessage();
        Throwable throwable = e.getCause();
        if (e != null) {
            if (throwable instanceof SocketTimeoutException) {
                SocketTimeoutException socketTimeoutException = (SocketTimeoutException) throwable;
                message = "服务调用超时" + socketTimeoutException.getMessage();
            }else if (e instanceof McpException) {
                McpException mcpException = (McpException) e;
                if(AppReply.MULTILOGIN_CODE.equals(mcpException.getMsgCode())
                        ||AppReply.LOGIN_CODE.equals(mcpException.getMsgCode()))
                {
                    return new AppReply(mcpException.getMsgCode(),mcpException.getMessage(),null);
                }
            }
        }

        if (StringUtils.isNotEmpty(e.getMessage()) && e.getMessage().startsWith(ERROR_MESSAGE_PREFIX)) {
            // 如果有前置报错，说明该类型的错误已经报了，所以保持原有错误 为了保持原始的报错点信息
            return AppReply.error(e.getMessage());
        } else {
            StringBuffer stringBuffer = new StringBuffer(ERROR_MESSAGE_PREFIX);
            stringBuffer.append(message);
            return AppReply.error(stringBuffer.toString());
        }
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public AppReply methodArgumentNotValidException(MethodArgumentNotValidException ex) {
        return AppReply.error(ex.getBindingResult().getFieldError().getDefaultMessage());
    }
}
